#include <curl.hpp>
#include <string>
#include <iostream>
#include <thread>

#include "api.h"

struct Info {
  bool lyric;
  std::ofstream of;
  Info(bool l, const char *f) : lyric(l), of(f) {}
  ~Info() { of.close(); }
  bool isOK() { return of.is_open(); }
};

static size_t writeFile(void *contents, size_t size, size_t num, void *udata) {
  auto info = (Info*)udata;
	size_t realSize = size * num;

	if (realSize && info) {
    info->of.write((const char*)contents, realSize);
	}

	return realSize;
}

curl::Easy createEasy(const char *url, const Info &info) {
  auto easy = curl::easy();
  if (easy) {
    easy->setopt(CURLoption::CURLOPT_URL, url);
    easy->setopt(CURLoption::CURLOPT_WRITEFUNCTION, writeFile);
    easy->setopt(CURLoption::CURLOPT_WRITEDATA, &info);
  }
  return std::move(easy);
}

int main(int argc, char *argv[]) {
  Info lyricInfo(true, "multi.lrc");
  Info musicInfo(false, "multi.mp3");

  if (!lyricInfo.isOK() || !musicInfo.isOK()) {
    std::cout << "open file error." << std::endl;
    return 0;
  }

  curl::globalInit(CURL_GLOBAL_ALL);

  auto lyric = createEasy(api::lyric, lyricInfo);
  auto music = createEasy(api::music, musicInfo);
  auto multi = curl::multi();
  if (lyric && music && multi) {
    multi->addHandle(lyric);
    multi->addHandle(music);

    int runningHandles = 0;
    int repeats = 0;
    do {
      int numfds;

      auto mc = multi->perform(&runningHandles);
      if (CURLMcode::CURLM_OK == mc)
        mc = multi->wait(nullptr, 0, 1000, &numfds);

      if (CURLMcode::CURLM_OK != mc) {
        std::cout << "perform error: " << curl::strError(mc) << std::endl;
        break;
      }

      if (!numfds) {
        ++repeats;
        if (repeats > 1)
          std::this_thread::sleep_for(std::chrono::milliseconds(100));
      } else {
        repeats = 0;
      }
    } while (runningHandles);
  }

  if (lyric) lyric->cleanup();
  if (music) music->cleanup();
  if (multi) multi->cleanup();
  curl::globalCleanup();

  std::cout << "DONE." << std::endl;
  return 0;
}